from datetime import datetime
from typing import List, Optional, Dict, Any
from bson import ObjectId
from ..database.mongodb import db_info_setting_collection
from ..utils.crypt_utils import encrypt_password, decrypt_password

class DBInfoSettingModel:
    """数据库连接信息模型，处理与MongoDB的交互"""
    
    collection = db_info_setting_collection
    
    @classmethod
    async def create(cls, db_info: Dict[str, Any], created_by: str = "system") -> Dict[str, Any]:
        """
        创建新的数据库连接信息
        
        Args:
            db_info: 数据库连接信息
            created_by: 创建人
            
        Returns:
            创建后的数据库连接信息，包含ID
        """
        # 在保存前加密密码
        if "password" in db_info and db_info["password"]:
            db_info["password"] = encrypt_password(db_info["password"])
            
        db_info["created_at"] = datetime.now()
        db_info["created_by"] = created_by
        db_info["updated_at"] = None
        db_info["updated_by"] = None
        
        result = await cls.collection.insert_one(db_info)
        
        # 获取创建的文档
        created_doc = await cls.collection.find_one({"_id": result.inserted_id})
        
        # 转换ObjectId为字符串
        created_doc["_id"] = str(created_doc["_id"])
        
        return created_doc
    
    @classmethod
    async def update(cls, id: str, db_info: Dict[str, Any], updated_by: str = "system") -> Optional[Dict[str, Any]]:
        """
        更新数据库连接信息
        
        Args:
            id: 数据库连接信息ID
            db_info: 需要更新的字段
            updated_by: 更新人
            
        Returns:
            更新后的数据库连接信息，如果ID不存在则返回None
        """
        try:
            # 在更新前加密密码
            if "password" in db_info and db_info["password"]:
                db_info["password"] = encrypt_password(db_info["password"])
                
            db_info["updated_at"] = datetime.now()
            db_info["updated_by"] = updated_by
            
            # 确保不更新创建信息
            if "created_at" in db_info:
                del db_info["created_at"]
            if "created_by" in db_info:
                del db_info["created_by"]
                
            # 更新文档
            await cls.collection.update_one(
                {"_id": ObjectId(id)},
                {"$set": db_info}
            )
            
            # 获取更新后的文档
            updated_doc = await cls.collection.find_one({"_id": ObjectId(id)})
            
            if updated_doc:
                # 转换ObjectId为字符串
                updated_doc["_id"] = str(updated_doc["_id"])
                return updated_doc
            return None
        except Exception:
            return None
    
    @classmethod
    async def find_by_id(cls, id: str) -> Optional[Dict[str, Any]]:
        """
        根据ID查询数据库连接信息
        
        Args:
            id: 数据库连接信息ID
            
        Returns:
            数据库连接信息，如果ID不存在则返回None
        """
        try:
            result = await cls.collection.find_one({"_id": ObjectId(id)})
            if result:
                # 转换ObjectId为字符串
                result["_id"] = str(result["_id"])
                return result
            return None
        except Exception:
            return None
        
    @classmethod
    async def find_by_connection_name(cls, connection_name: str,id:str = None) -> Optional[Dict[str, Any]]:
        """
        根据连接名称查询数据库连接信息
        
        Args:
            connection_name: 数据库连接名称
            
        Returns:
            数据库连接信息，如果不存在则返回None
        """
        try:
            query = {"connection_name": connection_name}
            if id:
                query["_id"] = {"$ne": ObjectId(id)}
            result = await cls.collection.find_one(query)
            if result:
                # 转换ObjectId为字符串
                result["_id"] = str(result["_id"])
                return result
            return result
        except Exception:
            return None
    
    @classmethod
    async def count(cls, query: Dict[str, Any] = None) -> int:
        """
        计算符合条件的文档数量
        
        Args:
            query: 查询条件
            
        Returns:
            文档数量
        """
        if query is None:
            query = {}
            
        # 创建查询条件
        find_query = {}
        
        # 添加可选过滤条件
        if "db_type" in query and query["db_type"]:
            find_query["db_type"] = query["db_type"]
        if "connection_name" in query and query["connection_name"]:
            find_query["connection_name"] = {"$regex": query["connection_name"], "$options": "i"}
        if "host" in query and query["host"]:
            find_query["host"] = {"$regex": query["host"], "$options": "i"}
            
        # 计算文档数量
        count = await cls.collection.count_documents(find_query)
        return count
    
    @classmethod
    async def find_all(cls, query: Dict[str, Any] = None, skip: int = 0, limit: int = 100) -> List[Dict[str, Any]]:
        """
        查询所有匹配条件的数据库连接信息，支持分页
        
        Args:
            query: 查询条件
            skip: 跳过的文档数量
            limit: 返回的最大文档数量
            
        Returns:
            数据库连接信息列表
        """
        if query is None:
            query = {}
        
        # 创建查询条件
        find_query = {}
        
        # 添加可选过滤条件
        if "db_type" in query and query["db_type"]:
            find_query["db_type"] = query["db_type"]
        if "connection_name" in query and query["connection_name"]:
            find_query["connection_name"] = {"$regex": query["connection_name"], "$options": "i"}
        if "host" in query and query["host"]:
            find_query["host"] = {"$regex": query["host"], "$options": "i"}
            
        # 查询并应用分页
        cursor = cls.collection.find(find_query).skip(skip).limit(limit)
        results = await cursor.to_list(length=limit)
        
        # 转换ObjectId为字符串
        for result in results:
            result["_id"] = str(result["_id"])
            
        return results
        
    @classmethod
    def decrypt_db_info(cls, db_info: Dict[str, Any]) -> Dict[str, Any]:
        """
        解密数据库连接信息中的密码
        
        Args:
            db_info: 包含加密密码的数据库连接信息
            
        Returns:
            解密后的数据库连接信息
        """
        if db_info and "password" in db_info and db_info["password"]:
            # 创建一个新的字典，避免修改原始对象
            decrypted_info = db_info.copy()
            decrypted_info["password"] = decrypt_password(db_info["password"])
            return decrypted_info
        return db_info